﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using VideoReflector.Models;

namespace VideoReflector.Controllers
{
    /// <summary>
    /// Controller object tasked with populating list of available Sessions to load for review from default save
    /// directory on disk and allowing load of session from user-defined locations
    /// </summary>
    public class SessionLoadController : NotifyingObject
    {
        #region Private fields

        IList<Session> _availableSessions;
        ICollectionView _availableSessionsView;
        ApplicationSettings _settings;

        #endregion // Private fields

        #region Constructor

        /// <summary>
        /// Constructor for SessionLoadController object
        /// </summary>
        /// <param name="settings"> Current application settings </param>
        public SessionLoadController(ApplicationSettings settings)
        {
            _settings = settings;
            // initialise session list
            _availableSessions = new List<Session>();
            // get list of file paths in default directory with Session file name pattern
            var sessionFilePaths = Directory.EnumerateFiles(settings.ExpandedDefaultSaveDirectory, "Session.xml", SearchOption.AllDirectories);
            // loop through each file path, try to load and if successful add to list
            foreach(var sessionFilePath in sessionFilePaths)
            {
                Session session;
                if (Session.LoadFromFile(sessionFilePath, out session))
                {
                    session.SaveDirectory = Path.GetDirectoryName(sessionFilePath);
                    _availableSessions.Add(session);
                }
            }
            _availableSessionsView = CollectionViewSource.GetDefaultView(_availableSessions);
        }

        #endregion // Constructor

        #region Public properties

        /// <summary>
        /// Public accessor for collection of session objects available to be loaded
        /// </summary>
        public IList<Session> AvailableSessions
        {
            get
            {
                return _availableSessions;
            }
            private set
            {
                if (_availableSessions != value)
                {
                    _availableSessions = value;
                    NotifyPropertyChanged("AvailableSessions");
                }
            }
        }

        #endregion // Public properties

        #region Events

        /// <summary>
        /// Event invoked when session load task has been finished
        /// </summary>
        public event EventHandler<SessionLoadFinishedEventArgs> Finished;

        #endregion // Events

        #region Commands
        
        #region OpenOtherLocation

        private RelayCommand _openOtherLocationCommand;

        /// <summary>
        /// Command to allow opening of session files in locations other than default directory using
        /// a file browser dialog
        /// </summary>
        public ICommand OpenOtherLocationCommand
        {
            get
            {
                if (_openOtherLocationCommand == null)
                {
                    _openOtherLocationCommand = new RelayCommand
                    (
                        param => this.OpenOtherLocation(),
                        param => this.CanOpenOtherLocation()
                    );
                }
                return _openOtherLocationCommand;
            }
        }

        private void OpenOtherLocation()
        {
            var openFileDialog = new Microsoft.Win32.OpenFileDialog();
            openFileDialog.Title = "Load previous session file";
            openFileDialog.CheckPathExists = true;
            openFileDialog.Multiselect = false;
            openFileDialog.Filter = "Extensible Markup Files (.xml)|*.xml";
            openFileDialog.InitialDirectory = _settings.ExpandedDefaultSaveDirectory;
            if(openFileDialog.ShowDialog() == true)
            {
                Session session;
                if(Session.LoadFromFile(openFileDialog.FileName, out session))
                {
                    session.SaveDirectory = System.IO.Path.GetDirectoryName(openFileDialog.FileName);
                    if (Finished != null)
                        Finished(this, new SessionLoadFinishedEventArgs(false, session));
                }
                else
                {
                    MessageBox.Show("Sorry chosen file is not a valid Video Reflector session", "Invalid file",    
                                        MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        private bool CanOpenOtherLocation()
        {
            return true;
        }

        #endregion // OpenOtherLocation  
        
        #region Ok

        private RelayCommand _okCommand;

        /// <summary>
        /// Select chosen session as current (selected) item in AvailableSessions collection view
        /// and fire Finished event passing chosen session
        /// </summary>
        public ICommand OkCommand
        {
            get
            {
                if (_okCommand == null)
                {
                    _okCommand = new RelayCommand
                    (
                        param => this.Ok(),
                        param => this.CanOk()
                    );
                }
                return _okCommand;
            }
        }

        private void Ok()
        {
            var chosenSession = (Session)_availableSessionsView.CurrentItem;
            if (Finished != null)
                Finished(this, new SessionLoadFinishedEventArgs(false, chosenSession));
        }

        private bool CanOk()
        {
            return _availableSessionsView != null && _availableSessionsView.CurrentItem != null && _availableSessionsView.CurrentItem is Session;
        }

        #endregion // Ok  
        
        #region Cancel

        private RelayCommand _cancelCommand;

        /// <summary>
        /// Fire Finished event indicating user has cancelled session load task
        /// </summary>
        public ICommand CancelCommand
        {
            get
            {
                if (_cancelCommand == null)
                {
                    _cancelCommand = new RelayCommand
                    (
                        param => this.Cancel(),
                        param => this.CanCancel()
                    );
                }
                return _cancelCommand;
            }
        }

        private void Cancel()
        {
            if (Finished != null) 
                Finished(this, new SessionLoadFinishedEventArgs(true, null));
        }

        private bool CanCancel()
        {
            return true;
        }

        #endregion // Cancel  
                        
        #endregion // Commands
    }
}
